﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace DebIt.Common.Model
{
    public class Loan : DbStoredItem
    {
        #region variables

        private string _name = "";
        private string _description = "";
        private string _currency = "";
        private decimal _loanValue;
        private decimal _loanPerClient;
        private DateTime _timeStamp = DateTime.Now;
        private readonly ObservableCollection<ClientLoanState> _clientLoanState = new ObservableCollection<ClientLoanState>();
        private readonly ObservableCollection<LoanItem> _loanItems = new ObservableCollection<LoanItem>();

        #endregion


        #region Constructor

        public Loan()
        {
            _loanItems.CollectionChanged += LoanItemsCollectionChanged;
            _clientLoanState.CollectionChanged += ClientLoanStateCollectionChanged;
        }

        ~Loan()
        {
            foreach (LoanItem li in _loanItems)
                li.PropertyChanged -= LoanItemPropertyChanged;
            _loanItems.CollectionChanged -= LoanItemsCollectionChanged;
            _clientLoanState.CollectionChanged -= ClientLoanStateCollectionChanged;
        }

        #endregion


        #region properties

        public int LoanId { get; set; }

        public string Name
        {
            get { return _name; }
            set
            {
                if (_name == value) return;
                SendPropertyChanging(() => Name);
                _name = value;
                SendPropertyChanged(() => Name);
            }
        }

        public string Description
        {
            get { return _description; }
            set
            {
                if (_description == value) return;
                SendPropertyChanging(() => Description);
                _description = value;
                SendPropertyChanged(() => Description);
            }
        }

        public string Currency
        {
            get { return _currency; }
            set
            {
                if (_currency == value) return;
                SendPropertyChanging(() => Currency);
                _currency = value;
                SendPropertyChanged(() => Currency);
            }
        }

        public decimal LoanValue
        {
            get { return _loanValue; }
            private set
            {
                if (_loanValue == value) return;
                SendPropertyChanging(() => LoanValue);
                _loanValue = value;
                SendPropertyChanged(() => LoanValue);
                CalculateLoanPerClient();
            }
        }

        public decimal LoanPerClient
        {
            get { return _loanPerClient; }
            private set
            {
                if (_loanPerClient == value) return;
                SendPropertyChanging(() => LoanPerClient);
                _loanPerClient = value;
                SendPropertyChanged(() => LoanPerClient);
            }
        }

        public DateTime TimeStamp
        {
            get { return _timeStamp; }
            set
            {
                if (_timeStamp == value) return;
                SendPropertyChanging(() => TimeStamp);
                _timeStamp = value;
                SendPropertyChanged(() => TimeStamp);
            }
        }

        public ObservableCollection<ClientLoanState> ClientLoanStates
        {
            get { return _clientLoanState; }
        }

        public ObservableCollection<LoanItem> LoanItems
        {
            get { return _loanItems; }
        }

        #endregion


        #region methode

        private void CalculateLoanValue()
        {
            var loanSum = LoanItems.Aggregate(0m, (x, y) => x + y.Value);
            LoanValue = Math.Round(loanSum, 2);
        }

        private void CalculateLoanPerClient()
        {
            var clientCount = _clientLoanState.Count == 0 ? 1 : _clientLoanState.Count;
            LoanPerClient = Math.Round(LoanValue / clientCount, 2);
        }

        public void Add(LoanItem loanItem)
        {
            LoanItems.Add(loanItem);
            loanItem.PropertyChanged += LoanItemPropertyChanged;
        }

        public void Add(List<LoanItem> loanItems)
        {
            loanItems.ForEach(Add);
        }

        public List<LoanItem> GetAllLoanItems()
        {
            return LoanItems.ToList();
        }

        public bool Remove(LoanItem loanItem)
        {
            loanItem.PropertyChanged -= LoanItemPropertyChanged;
            return _loanItems.Remove(loanItem);
        }

        void LoanItemPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals("Value"))
                CalculateLoanValue();
        }

        void LoanItemsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            CalculateLoanValue();
        }

        void ClientLoanStateCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            CalculateLoanPerClient();
        }

        #endregion

    }
}
